﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace BaseAPI.BaseModel;

public class PatchModel<T> where T : BaseEntity
{
    public T Model { get; set; }
    public Action<T, DbContext> PatchFun { get; set; }
}

/// <summary>
/// 数据库层面的增删查改
/// </summary>
/// <typeparam name="T">实体</typeparam>
public class ModelServer<T>(DbContext dataContext) : IDisposable
    where T : BaseEntity, new()
{
    public DbContext DataContext = dataContext;

    #region 添加一个或多个

    /// <summary>
    /// 添加一个实体
    /// </summary>
    /// <param name="t">实体</param>
    /// <returns>新实体ID</returns>
    public async Task<long> Add(T t)
    {
        if (IsEmpty(t))
            return 0;
        DataContext.Set<T>().Add(t);
        await DataContext.SaveChangesAsync();
        return t.ID;
    }

    /// <summary>
    /// 添加多个实体
    /// </summary>
    /// <param name="listT">实体列表</param>
    /// <returns>新实体ID列表</returns>
    public async Task<List<long>> Add(List<T> listT)
    {
        if (IsEmpty(listT))
            return null;
        DataContext.Set<T>().AddRange(listT);
        await DataContext.SaveChangesAsync();
        return listT.Select(x => x.ID).ToList();
    }

    #endregion

    #region 删除一个或多个

    /// <summary>
    /// 删除一个实体
    /// </summary>
    /// <param name="id">实体ID</param>
    /// <returns>成功执行的数量</returns>
    public async Task<int> Remove(long id)
    {
        T t = new() { ID = id };
        DataContext.Entry(t).State = EntityState.Deleted;
        return await DataContext.SaveChangesAsync();
    }

    /// <summary>
    /// 删除一个实体
    /// </summary>
    /// <param name="t">实体</param>
    /// <returns>成功执行的数量</returns>
    public async Task<int> Remove(T t)
    {
        if (IsEmpty(t))
            return 0;
        DataContext.Entry(t).State = EntityState.Deleted;
        return await DataContext.SaveChangesAsync();
    }

    /// <summary>
    /// 删除多个实体
    /// </summary>
    /// <param name="ids">实体ID列表</param>
    /// <returns>成功执行的数量</returns>
    public async Task<int> Remove(List<long> ids)
    {
        if (IsEmpty(ids))
            return 0;
        ids.ForEach(x =>
        {
            var t = new T { ID = x };
            DataContext.Entry(t).State = EntityState.Deleted;
        });
        return await DataContext.SaveChangesAsync();
    }

    /// <summary>
    /// 删除多个实体
    /// </summary>
    /// <param name="listT">实体列表</param>
    /// <returns>成功执行的数量</returns>
    public async Task<int> Remove(List<T> listT)
    {
        if (IsEmpty(listT))
            return 0;
        listT.ForEach(x => DataContext.Entry(x).State = EntityState.Deleted);
        return await DataContext.SaveChangesAsync();
    }

    #endregion

    #region 修改一个或多个

    /// <summary>
    /// 更新实体（Put），如果传入patchFun则为部分更新（Patch）
    /// </summary>
    /// <param name="t">实体</param>
    /// <param name="patchFun">部分更新函数</param>
    /// <returns>成功执行的数量</returns>
    public async Task<int> Modify(T t, Action<T, DbContext> patchFun = null)
    {
        if (IsEmpty(t))
            return 0;
        if (patchFun == null)
            DataContext.Entry(t).State = EntityState.Modified;
        else
        {
            DataContext.Entry(t).State = EntityState.Unchanged;
            patchFun(t, DataContext);
        }

        return await DataContext.SaveChangesAsync();
    }

    /// <summary>
    /// 更新实体列表（Put），如果传入patchFun则为部分更新（Patch）
    /// </summary>
    /// <param name="patchModels">更新实体列表</param>
    /// <returns>成功执行的数量</returns>
    public async Task<int> Modify(List<PatchModel<T>> patchModels)
    {
        foreach (var x in patchModels)
        {
            if (IsEmpty(x.Model))
                return 0;
            if (x.PatchFun == null)
                DataContext.Entry(x).State = EntityState.Modified;
            else
            {
                dataContext.Entry(x.Model).State = EntityState.Unchanged;
                x.PatchFun(x.Model, dataContext);
            }
        }

        return await DataContext.SaveChangesAsync();
    }

    #endregion

    #region 查询

    /// <summary>
    /// 查询返回多个
    /// </summary>
    /// <returns>返回NoTracking的IQueryable</returns>
    public IQueryable<T> GetList()
    {
        return DataContext.Set<T>().AsNoTracking();
    }

    /// <summary>
    /// 查询返回一个（查询ID）
    /// </summary>
    /// <param name="id">实体ID</param>
    /// <returns>返回FirstOrDefault</returns>
    public async Task<T> GetOne(long id)
    {
        return await GetList().FirstOrDefaultAsync(x => x.ID == id);
    }

    /// <summary>
    /// 查询返回一个（查询'查询函数'）
    /// </summary>
    /// <param name="queryFun">查询函数</param>
    /// <returns>返回FirstOrDefault</returns>
    public async Task<T> GetOne(Func<IQueryable<T>, IQueryable<T>> queryFun)
    {
        return await queryFun(GetList()).FirstOrDefaultAsync();
    }

    /// <summary>
    /// 查询返回一个（查询ID和转换函数）
    /// </summary>
    /// <typeparam name="TU">返回类型</typeparam>
    /// <param name="id">实体ID</param>
    /// <param name="transFun">转换函数</param>
    /// <returns>返回FirstOrDefault</returns>
    public async Task<TU> GetOne<TU>(long id, Func<IQueryable<T>, IQueryable<TU>> transFun)
    {
        return await transFun(GetList().Where(x => x.ID == id)).FirstOrDefaultAsync();
    }

    /// <summary>
    /// 查询返回一个（查询'转换函数'）
    /// </summary>
    /// <typeparam name="TU">返回类型</typeparam>
    /// <param name="transFun">转换函数</param>
    /// <returns>返回FirstOrDefault</returns>
    public async Task<TU> GetOne<TU>(Func<IQueryable<T>, IQueryable<TU>> transFun)
    {
        return await transFun(GetList()).FirstOrDefaultAsync();
    }

    #endregion

    #region 私有方法[IsEmpty]，判断实体、实体列表、实体ID列表是否为空

    private static bool IsEmpty(T t)
    {
        return t == null;
    }

    private static bool IsEmpty(List<T> lt)
    {
        return lt == null || lt.Count == 0;
    }

    private static bool IsEmpty(List<long> ll)
    {
        return ll == null || ll.Count == 0;
    }

    #endregion

    public void Dispose()
    {
        DataContext = null;
    }
}